module HSimMath where

import Data.List

-- Представление точки в 2-ух мерном пространстве

type Point2D = (Double, Double)

-- Представление вектора в 2-ух мерном пространстве

type Vector2D = (Double, Double)

-- Сложение двух точек

(<+>) :: Point2D -> Point2D -> Point2D
(x, y) <+> (u, v) = (x+u, y+v)

-- Сложение двух точек

(<->) :: Point2D -> Point2D -> Point2D
(x, y) <-> (u, v) = (x-u, y-v)

-- Умножение двух точек

(<*>) :: Point2D -> Point2D -> Point2D
(x, y) <*> (u, v) = (x*u, y*v)

-- Умножение точки на число

(*>) :: Point2D -> Double -> Point2D
(x, y) *> f = (x*f, y*f)

-- Умножение точки на число

(+>) :: Point2D -> Double -> Point2D
(x, y) +> f = (x+f, y+f)

-- Скалярное произведения двух векторов

(*.) :: Vector2D -> Vector2D -> Double
(x, y) *. (u, v) = x*u + y*v

-- "Векторное" произведение в плоскости, равное ориентированной площади параллелограмма натянутого на вектора.
-- Или определитель матрицы, строками которой являются координаты векторов.

(.*) :: Vector2D -> Vector2D -> Double
(x, y) .* (u, v) = x*v - u*y

-- Oпределение нормы

norm :: (Double, Double) -> (Double, Double) -> Double
norm (x, y) (u, v) = sqrt $ (x-u)^2 + (y-v)^2

-- Альтернативное определение нормы

norm' :: (Double, Double) -> (Double, Double) -> Double
norm' (x, y) (u, v) = max ( abs (x-u) ) ( abs (y-v) )

-- Функции округления пары

floor2 :: (RealFrac a, Num b) => (a, a) -> (b, b)
floor2 (x, y) = (fromInteger $ floor x, fromInteger $ floor y)

ceiling2 :: (RealFrac a, Num b) => (a, a) -> (b, b)
ceiling2 (x, y) = (fromInteger $ ceiling x, fromInteger $ ceiling y)

round2 :: (RealFrac a, Num b) => (a, a) -> (b, b)
round2 (x, y) = (fromInteger $ round x, fromInteger $ round y)


-- Численное интегрирование функции 2-ух аргументов

quad' :: (RealFrac a, RealFrac b, Enum a) => Int -> (a,a) -> (a -> b) -> b
quad' n (a, b) func = s * (fromRational $ toRational dx)
   where
       dx = (b-a) / fromIntegral n
       s  = foldl' (+) 0 $ map func [a+0.5*dx, a+1.5*dx .. b-0.5*dx]

quad :: (RealFrac a, RealFrac b, Enum a) => (a,a) -> (a -> b) -> b
quad = quad' 10

quad2 :: (RealFrac a, RealFrac b, RealFrac c, Enum a, Enum b) => (a,a) -> (b,b) -> (a -> b -> c) -> c
quad2 xb yb func = quad xb $ \x-> quad yb $ func x

quad3 :: (RealFrac a, RealFrac b, RealFrac c, RealFrac d, Enum a, Enum b, Enum c) => (a,a) -> (b,b)->(c,c) -> (a -> b -> c -> d) -> d
quad3 xb yb zb func = quad xb $ \x-> quad2 yb zb $ func x